package main

import (
	"alas-notify/config"
	"bytes"
	"context"
	"crypto/tls"
	"encoding/json"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
	"github.com/fsnotify/fsnotify"
	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
	"io"
	"log"
	"net/http"
	"time"
)

func init() {
	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath(".")
	err := viper.ReadInConfig()
	if err != nil {
		log.Fatalf("配置文件读取失败: %v", err)
	}
	err = viper.Unmarshal(&config.Conf)
	if err != nil {
		log.Fatalf("配置文件类型转换失败: %v", err)
	}

	// 监听配置文件修改
	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		err := viper.Unmarshal(&config.Conf)
		if err != nil {
			log.Printf("配置文件类型转换失败: %v\n", err)
			return
		}
		log.Printf("配置文件修改(%s): %s\n", time.Now().Format("2006-01-01 15:04:05"), e.Name)
	})
}

func main() {
	gin.SetMode(config.Conf.Mode)
	r := gin.Default()
	r.GET("/", func(c *gin.Context) {
		c.String(200, "服务启动成功")
	})
	r.GET("/notify", func(c *gin.Context) {
		res := ""
		if config.Conf.Notify.Active {
			res = sendNotify(c.Query("title"), c.Query("content"))
		} else {
			res = "消息方法禁用"
		}
		if config.Conf.Docker.Restart && config.Counter.AllowExecution(config.Conf.Docker.Retry) {
			log.Println("执行容器重启。。。")
			go func() {
				time.Sleep(30 * time.Second)
				restartContainer()
			}()
		}
		c.String(200, res)
	})
	err := r.Run(":8000")
	if err != nil {
		log.Fatalf("服务启动失败: %v", err)
	}
}

func sendNotify(title string, content string) string {
	if config.Conf.Notify.Active {
		data := config.Conf.Notify.Data
		data["title"] = title
		data["content"] = content
		jsonData, _ := json.Marshal(data)
		payload := bytes.NewBuffer(jsonData)
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
		httpClient := &http.Client{Transport: tr}
		response, err := httpClient.Post(config.Conf.Notify.Url, "application/json", payload)
		if err != nil {
			log.Println("Notify请求失败: " + err.Error())
			return "Notify请求失败"
		}
		defer func(Body io.ReadCloser) {
			err := Body.Close()
			if err != nil {
			}
		}(response.Body)
		body, err := io.ReadAll(response.Body)
		if err != nil {
			log.Println("Notify读取响应失败: " + err.Error())
			return "Notify读取响应失败"
		}
		return string(body)
	}
	return "成功了捏"
}

func restartContainer() {
	ctx := context.Background()
	cli, _ := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	err := cli.ContainerRestart(ctx, config.Conf.Docker.Container, container.StopOptions{})
	if err != nil {
		log.Println(err)
	} else {
		log.Println("restart success ", config.Conf.Docker.Container)
	}
}
